package com.hzw.saas.service.workspace.service;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import com.hzw.saas.api.workspace.IFileManagerService;
import com.hzw.saas.api.workspace.bo.UserWorkspaceFileBo;
import com.hzw.saas.api.workspace.enms.FileType;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.util.PathUtils;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.PathUtil;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import jodd.util.StringUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 *
 * </p>
 *
 * @author sonam
 * @since 2021/2/2 11:44
 */
@Service
@Slf4j
@AllArgsConstructor
public class FileManagerServiceImpl implements IFileManagerService {

    @Override
    public File createDir(String dirPath) {
        File dir = FileUtil.file(dirPath);
        if (FileUtil.exist(dir)) {
            return dir; // skip
        }
        AssertUtil.assertThrow(String.format("创建目录[%s]失败", dir.getName()), !dir.mkdirs());
        log.debug("创建目录[{}]成功", dir.getAbsolutePath());
        return dir;
    }

    @Override
    public void removeDir(String path, boolean rf) {
        AssertUtil.assertThrow("目录路径不能为空", StringUtil.isBlank(path));
        File file = FileUtil.file(path);
        path = file.getAbsolutePath();
        if (rf || FileUtil.isFile(file)) {
            log.debug("delete file: {}", file);
            boolean del = PathUtil.del(file.toPath());
            // boolean del = FileUtil.del(file);
            log.debug("delete file over: {}", del);
            return;
        }
        AssertUtil.assertThrow(String.format("删除目录失败,刪除的目录[%s]不为空", file.getName()),
            FileUtil.loopFiles(file).size() != 0);
        FileUtil.del(path);
    }

    @Override
    public File rename(String path, String name) {
        File file = FileUtil.file(path);
        AssertUtil.assertThrow(String.format("重命名文件失败，文件[%s]不存在", file.getName()), !FileUtil.exist(file));
        AssertUtil.assertThrow(String.format("重命名文件失败，文件[%s]已存在", name), FileUtil.exist(new File(file.getParent(), name)));
        return FileUtil.rename(file, name, false, false);
    }

    @Override
    public void move(String path, String targetPath) {
        AssertUtil.assertThrow("移动失败，目标路径与源路径相同", Objects.equals(FileUtil.file(path).getAbsolutePath(), FileUtil.file(targetPath).getAbsolutePath()));
        AssertUtil.assertThrow("移动失败，目标文件夹是源文件夹的子文件", PathUtils.isSub(path, targetPath));
        AssertUtil.assertThrow("复制失败，目标文件存在", new File(FileUtil.file(targetPath), FileUtil.file(path).getName()).exists());
        FileUtil.copy(path, targetPath, false);
        FileUtil.del(path);
    }

    @Override
    public void copy(String path, String targetPath) {
        AssertUtil.assertThrow("复制失败，目标路径与源路径相同", Objects.equals(FileUtil.file(path).getAbsolutePath(), FileUtil.file(targetPath).getAbsolutePath()));
        AssertUtil.assertThrow("复制失败，目标文件夹是源文件夹的子文件", PathUtils.isSub(path, targetPath));
        AssertUtil.assertThrow("复制失败，目标文件存在", new File(FileUtil.file(targetPath), FileUtil.file(path).getName()).exists());
        FileUtil.copy(path, targetPath, false);
    }

    @Override
    public List<UserWorkspaceFileBo> getFileList(String path) {
        List<UserWorkspaceFileBo> fileList = new ArrayList<>();
        File dir = FileUtil.file(path);
        if (!dir.isDirectory()) return fileList;
        File[] files = FileUtil.ls(path);
        for (File file : files) {
            fileList.add(new UserWorkspaceFileBo(
                file.getName(),
                file.isDirectory() ? FileType.DIR.value() : FileType.FILE.value(),
                file.isDirectory() ? 0 : FileUtil.size(file),
                FileUtil.lastModifiedTime(file)
            ));
        }
        return fileList;
    }

    @Override
    public void uploadFile(MultipartFile file, String path) {
        try {
            // 判断当前路径是否又重名文件
            String filepath = PathUtils.connectPath(path, file.getOriginalFilename());
            int index = 1;
            while (FileUtil.file(filepath).exists()) {
                String fileName = FileUtil.getName(file.getOriginalFilename());
                String suffix = FileUtil.getSuffix(file.getOriginalFilename());
                filepath = PathUtils.connectPath(path, String.format("%s（%d）.%s",fileName, index++, suffix));
            }
            FileUtil.writeBytes(file.getBytes(), filepath);
        } catch (IOException e) {
            AssertUtil.assertThrow("上传文件失败，写入文件数据异常",true);
        }
    }

    @Override
    public void downloadFile(String filepath, OutputStream os) {
        File file = FileUtil.file(filepath);
        AssertUtil.assertThrow("下载文件失败，文件不存在请刷新或者重试", !FileUtil.exist(file));
        AssertUtil.assertThrow("下载文件失败，不能下载目录", !FileUtil.isFile(file));
        IoUtil.copy(IoUtil.toStream(file), os);
    }

    @Override
    public long getFileCount(String dirPath) {
        return FileUtil.loopFiles(dirPath).size();
    }

    @Override
    public long getFileSize(String dirPath) {
        return FileUtil.size(FileUtil.file(dirPath)) ;
    }
}
